// PulsarXyyyzText
//
// Se modifico la lista de UUID de las texturas que usa el script 
// Julio 14 de 2010 
// marlonj

////////////////////////////////////////////
// XyText v1.0.3 Script (5 Face, Multi Texture)
//
// Written by Xylor Baysklef
//
// Modified by Thraxis Epsilon January 20, 2006
// Added Support for 5 Face Prim, based on modification
// of [[XyText]] v1.1.1 by Kermitt Quick for Single Texture.
//
////////////////////////////////////////////
 
/////////////// CONSTANTS ///////////////////
// XyText Message Map.
integer DISPLAY_STRING      = 204000;
integer DISPLAY_EXTENDED    = 204001;
integer REMAP_INDICES       = 204002;
integer RESET_INDICES       = 204003;
integer SET_CELL_INFO       = 204004;
integer SET_THICKNESS       = 204006;
integer SET_COLOR           = 204007;
 
// This is an extended character escape sequence.
string  ESCAPE_SEQUENCE = "\\e";
 
// This is used to get an index for the extended character.
string  EXTENDED_INDEX  = "123456789abcdef";
 
// Face numbers.
integer FACE_1          = 3;
integer FACE_2          = 7;
integer FACE_3          = 4;
integer FACE_4          = 6;
integer FACE_5          = 1;
 
// Used to hide the text after a fade-out.
key        TRANSPARENT     = "701917a8-d614-471f-13dd-5f4644e36e3c";
// This is a list of textures for all 2-character combinations.
list    CHARACTER_GRID  = [
"b8b036aa-e767-4511-8d36-0cc11e65e2a2",
"81c4dcaf-46f2-4a9f-97be-547275169228",
"65fb7568-fc6b-46b8-9b10-e88ee3ec780e",
"38215dcd-d3cf-4c80-9e5d-af6de2e4535a",
"8d79773e-cece-4197-a13d-6ea5f29d0243",
"048a7142-2bf3-4d50-92f6-6e10bf445e31",
"db4dad03-922c-48b2-9a6b-ae988bff5bbf",
"8de53dec-87c5-4a6a-9908-10f6de3cb058",
"9911fc5e-b308-4dcd-90b7-95970a43f45f",
"4a36f92a-bedd-4a53-8d19-f27665e7e8fb",
"f3bf1cd4-fb2c-46c6-bb1d-d7a1cd01182b",
"3a65eb53-13eb-4889-901b-88e9319ca3c7",
"24016555-80d5-4958-b1c1-37a6f0286fe1",
"889dad17-0566-4534-884e-c98f4aa30030",
"767bfc28-34bd-4526-8b22-a833ffc125bd",
"a0def462-a9f7-45ca-98dd-1607b8d29391",
"b95de0fc-03b3-4b34-8a38-65e448e3baac",
"38f008d0-c2ad-4aa9-b759-bfaf0ca32954",
"c4bc35d4-1d3b-4f14-8dd4-4e0160e88a84",
"aca68b32-028c-425f-8b37-165e7df6bfef",
"0ef69d13-462b-461a-933f-d1c9a8ff361e",
"b0ae48f5-9206-4b1b-b7ed-f69a7f838d3e",
"fcfee748-49c3-4e5a-9103-176e2ef0eec9",
"2272a6a7-aff4-478c-a5fe-4efad0162415",
"9fb4b328-9905-462b-bb09-6fe6729658bd",
"2b4fc16e-b2b9-4606-bc40-4a5d1d0e6f56",
"c3b2f5a4-5ea6-4931-ac27-4aff21bd3249",
"3edf4657-ba0c-4725-a08b-ea34033b43fb",
"f91f5058-5bb5-4f80-aadc-2246950f804e",
"d6f7ff01-ed52-427c-9d73-4c01177095d9",
"3162b376-9dc6-4a82-92d1-78dad7c4d2a6",
"2c81c073-c69c-4a05-9c82-a4ee7466fbba",
"f56a9362-781f-4a06-898d-feb764ad8744",
"b9f29da2-8a12-4078-a9d6-72b690f491b7",
"80a7350a-9d2b-407c-b2b1-33b7bf4c33dc",
"cbb95b9f-becc-477c-92ac-869877be622f",
"3f3218a1-5c40-4ec0-a1fc-18066718f404",
"a296f9d6-843c-45a3-ab69-a3f5d4391ffb",
"d89f0dd5-418f-4472-a628-ed7e42808427",
"c13ea6e3-7a63-47f9-989e-c2a7dacf11d9",
"db4754b4-2870-445e-87c8-57d841faaf85",
"3b8ebb54-0395-4538-9587-03cff8fd9d26",
"0340ba3f-6f80-4a6a-9c19-a0cb53feba99",
"78767201-447c-4a2e-969c-b68413a13041",
"6d4430c1-7b64-4bc2-81a2-e12fab51e823",
"5bb4e8f5-36a0-441a-a650-923115f71b02",
"77ddb879-36da-414a-9abe-4c103da25803",
"9199b730-463a-405a-a402-b0e27be8b36c",
"bb42f070-509d-41ff-ba15-7bf455986459",
"17427d71-60af-487e-a7cc-6518bc8d2a8e",
"c7d9a8b0-fe77-48a7-bd27-ef71bbe4462a",
"78c0391a-3b31-4acb-9e93-5bbdd1e6a3dd",
"49996734-9aa9-42e4-85f1-e4e25b8cef0b",
"28f60575-d0a4-41d9-8460-257e2cd09d33",
"f792b813-0b49-423e-aba9-06b316ebaef6",
"9ee5e361-9de4-4446-9ed7-017d8163d10c",
"40f37689-f184-43dc-94e7-0fce2f1d04de",
"0e44797e-5261-49d7-956c-f972b8eb2821",
"7fc6c06f-950e-4225-b978-c7938c56b035",
"bb6656d3-0654-4082-9c3c-a3dc311dc788",
"6be176e7-0512-4c4a-a5ba-9f4851e80aa8",
"f00a177c-d0ee-42f1-9970-d7fe8b9cca32",
"2cc2cf99-4d9f-4f3f-b506-b5d98b59d56e",
"b24a9650-5e39-4328-8677-e826f7853f00",
"1d779a72-9e02-4c6a-a7b4-c32bd1e692f3",
"7890ccf3-30f6-4bdb-9045-dec7a77424d9" 
       ];
 
///////////// END CONSTANTS ////////////////
 
///////////// GLOBAL VARIABLES ///////////////
// All displayable characters.  Default to ASCII order.
string gCharIndex;
// This is the channel to listen on while acting
// as a cell in a larger display.
integer gCellChannel      = -1;
// This is the starting character position in the cell channel message
// to render.
integer gCellCharPosition = 0;
// This is whether or not to use the fade in/out special effect.
integer gCellUseFading      = FALSE;
// This is how long to display the text before fading out (if using
// fading special effect).
// Note: < 0  means don't fade out.
float   gCellHoldDelay      = 1.0;
/////////// END GLOBAL VARIABLES ////////////
 
ResetCharIndex() {
    gCharIndex  = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
    // \" <-- Fixes LSL syntax highlighting bug.
    gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~";
    gCharIndex += "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
}
 
vector GetGridPos(integer index1, integer index2) {
    // There are two ways to use the lookup table...
    integer Col;
    integer Row;
    if (index1 >= index2) {
        // In this case, the row is the index of the first character:
        Row = index1;
        // And the col is the index of the second character (x2)
        Col = index2 * 2;
    }
    else { // Index1 < Index2
        // In this case, the row is the index of the second character:
        Row = index2;
        // And the col is the index of the first character, x2, offset by 1.
        Col = index1 * 2 + 1;
    }
    return <Col, Row, 0>;
}
 
string GetGridTexture(vector grid_pos) {
    // Calculate the texture in the grid to use.
    integer GridCol = llRound(grid_pos.x) / 20;
    integer GridRow = llRound(grid_pos.y) / 10;
 
    // Lookup the texture.
    key Texture = llList2Key(CHARACTER_GRID, GridRow * (GridRow + 1) / 2 + GridCol);
    return Texture;
}
 
vector GetGridOffset(vector grid_pos) {
    // Zoom in on the texture showing our character pair.
    integer Col = llRound(grid_pos.x) % 20;
    integer Row = llRound(grid_pos.y) % 10;
 
    // Return the offset in the texture.
    return <-0.45 + 0.05 * Col, 0.45 - 0.1 * Row, 0.0>;
}
 
ShowChars(vector grid_pos1, vector grid_pos2, vector grid_pos3, vector grid_pos4, vector grid_pos5) {
   // Set the primitive textures directly.
 
 
    llSetPrimitiveParams( [
        PRIM_TEXTURE, FACE_1, GetGridTexture(grid_pos1), <0.25, 0.1, 0>, GetGridOffset(grid_pos1) + <0.075, 0, 0>, 0.0,
        PRIM_TEXTURE, FACE_2, GetGridTexture(grid_pos2), <0.1, 0.1, 0>, GetGridOffset(grid_pos2), 0.0,
        PRIM_TEXTURE, FACE_3, GetGridTexture(grid_pos3), <-1.48, 0.1, 0>, GetGridOffset(grid_pos3)+ <0.37, 0, 0>, 0.0,
        PRIM_TEXTURE, FACE_4, GetGridTexture(grid_pos4), <0.1, 0.1, 0>, GetGridOffset(grid_pos4), 0.0,
        PRIM_TEXTURE, FACE_5, GetGridTexture(grid_pos5), <0.25, 0.1, 0>, GetGridOffset(grid_pos5) - <0.075, 0, 0>, 0.0
        ]);
}
 
RenderString(string str) {
    // Get the grid positions for each pair of characters.
    vector GridPos1 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );
    vector GridPos2 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );
    vector GridPos3 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 5, 5)) );
    vector GridPos4 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 6, 6)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 7, 7)) );
    vector GridPos5 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 8, 8)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 9, 9)) );                                   
 
    // Use these grid positions to display the correct textures/offsets.
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);
}
 
RenderWithEffects(string str) {
    // Get the grid positions for each pair of characters.
    vector GridPos1 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );
    vector GridPos2 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );
    vector GridPos3 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 5, 5)) );
    vector GridPos4 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 6, 6)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 7, 7)) );
    vector GridPos5 = GetGridPos( llSubStringIndex(gCharIndex, llGetSubString(str, 8, 8)),
                                  llSubStringIndex(gCharIndex, llGetSubString(str, 9, 9)) );                                   
 
      // First set the alpha to the lowest possible.
    llSetAlpha(0.05, ALL_SIDES);
 
    // Use these grid positions to display the correct textures/offsets.
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);
 
    float Alpha;
    for (Alpha = 0.10; Alpha <= 1.0; Alpha += 0.05)
       llSetAlpha(Alpha, ALL_SIDES);
    // See if we want to fade out as well.
    if (gCellHoldDelay < 0.0)
       // No, bail out. (Just keep showing the string at full strength).
       return;
    // Hold the text for a while.
    llSleep(gCellHoldDelay);
    // Now fade out.
    for (Alpha = 0.95; Alpha >= 0.05; Alpha -= 0.05)
        llSetAlpha(Alpha, ALL_SIDES);
    // Make the text transparent to fully hide it.
    llSetTexture(TRANSPARENT, ALL_SIDES);
}
 
RenderExtended(string str) {
    // Look for escape sequences.
    list Parsed       = llParseString2List(str, [], [ESCAPE_SEQUENCE]);
    integer ParsedLen = llGetListLength(Parsed);
 
    // Create a list of index values to work with.
    list Indices;
    // We start with room for 6 indices.
    integer IndicesLeft = 10;
 
    integer i;
    string Token;
    integer Clipped;
    integer LastWasEscapeSequence = FALSE;
    // Work from left to right.
    for (i = 0; i < ParsedLen && IndicesLeft > 0; i++) {
        Token = llList2String(Parsed, i);
 
        // If this is an escape sequence, just set the flag and move on.
        if (Token == ESCAPE_SEQUENCE) {
            LastWasEscapeSequence = TRUE;
        }
        else { // Token != ESCAPE_SEQUENCE
            // Otherwise this is a normal token.  Check its length.
            Clipped = FALSE;
            integer TokenLength = llStringLength(Token);
            // Clip if necessary.
            if (TokenLength > IndicesLeft) {
                Token = llGetSubString(Token, 0, IndicesLeft - 1);
                TokenLength = llStringLength(Token);
                IndicesLeft = 0;
                Clipped = TRUE;
            }
            else
                IndicesLeft -= TokenLength;
 
            // Was the previous token an escape sequence?
            if (LastWasEscapeSequence) {
                // Yes, the first character is an escape character, the rest are normal.
 
                // This is the extended character.
                Indices += [llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95];
 
                // These are the normal characters.
                integer j;
                for (j = 1; j < TokenLength; j++)
                    Indices += [llSubStringIndex(gCharIndex, llGetSubString(Token, j, j))];
            }
            else { // Normal string.
                // Just add the characters normally.
                integer j;
                for (j = 0; j < TokenLength; j++)
                    Indices += [llSubStringIndex(gCharIndex, llGetSubString(Token, j, j))];
            }
 
            // Unset this flag, since this was not an escape sequence.
            LastWasEscapeSequence = FALSE;
        }
    }
 
    // Use the indices to create grid positions.
    vector GridPos1 = GetGridPos( llList2Integer(Indices, 0), llList2Integer(Indices, 1) );
    vector GridPos2 = GetGridPos( llList2Integer(Indices, 2), llList2Integer(Indices, 3) );
    vector GridPos3 = GetGridPos( llList2Integer(Indices, 4), llList2Integer(Indices, 5) );
    vector GridPos4 = GetGridPos( llList2Integer(Indices, 6), llList2Integer(Indices, 7) );
    vector GridPos5 = GetGridPos( llList2Integer(Indices, 8), llList2Integer(Indices, 9) );     
 
    // Use these grid positions to display the correct textures/offsets.
    ShowChars(GridPos1, GridPos2, GridPos3, GridPos4, GridPos5);
}
 
integer ConvertIndex(integer index) {
    // This converts from an ASCII based index to our indexing scheme.
    if (index >= 32) // ' ' or higher
        index -= 32;
    else { // index < 32
        // Quick bounds check.
        if (index > 15)
            index = 15;
 
        index += 94; // extended characters
    }
 
    return index;
}
 
default {
    state_entry() {
        // Initialize the character index.
        ResetCharIndex();
 
        //llSay(0, "Free Memory: " + (string) llGetFreeMemory());
    }
 
    link_message(integer sender, integer channel, string data, key id) {
        if (channel == DISPLAY_STRING) {
            RenderString(data);
            return;
        }
        if (channel == DISPLAY_EXTENDED) {
            RenderExtended(data);
            return;
        }
        if (channel == gCellChannel) {
            // Extract the characters we are interested in, and use those to render.
            string TextToRender = llGetSubString(data, gCellCharPosition, gCellCharPosition + 9);
            if (gCellUseFading)
               RenderWithEffects( TextToRender );
            else // !gCellUseFading
                RenderString( TextToRender );
            return;
        }
        if (channel == REMAP_INDICES) {
            // Parse the message, splitting it up into index values.
            list Parsed = llCSV2List(data);
            integer i;
            // Go through the list and swap each pair of indices.
            for (i = 0; i < llGetListLength(Parsed); i += 2) {
                integer Index1 = ConvertIndex( llList2Integer(Parsed, i) );
                integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) );
 
                // Swap these index values.
                string Value1 = llGetSubString(gCharIndex, Index1, Index1);
                string Value2 = llGetSubString(gCharIndex, Index2, Index2);
 
                gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1);
                gCharIndex = llInsertString(gCharIndex, Index1, Value2);
 
                gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2);
                gCharIndex = llInsertString(gCharIndex, Index2, Value1);
            }
            return;
        }
        if (channel == RESET_INDICES) {
            // Restore the character index back to default settings.
            ResetCharIndex();
            return;
        }
        if (channel == SET_CELL_INFO) {
            // Change the channel we listen to for cell commands, and the
            // starting character position to extract from.
            list Parsed = llCSV2List(data);
            gCellChannel        = (integer) llList2String(Parsed, 0);
            gCellCharPosition   = (integer) llList2String(Parsed, 1);
            gCellUseFading      = (integer) llList2String(Parsed, 2);
            gCellHoldDelay      = (float)   llList2String(Parsed, 3);             
            return;
        }
        if (channel == SET_THICKNESS) {
            // Set our z scale to thickness, while staying fixed
            // in position relative the prim below us.
            vector Scale    = llGetScale();
            float Thickness = (float) data;
            // Reposition only if this isn't the root prim.
            integer ThisLink = llGetLinkNumber();
            if (ThisLink != 0 || ThisLink != 1) {
                // This is not the root prim.
                vector Up = llRot2Up(llGetLocalRot());
                float DistanceToMove = Thickness / 2.0 - Scale.z / 2.0;
                vector Pos = llGetLocalPos();
                llSetPos(Pos + DistanceToMove * Up);
            }
            // Apply the new thickness.
            Scale.z = Thickness;
            llSetScale(Scale);
            return;
        }
        if (channel == SET_COLOR) {
           vector newColor = (vector)data;
           llSetColor(newColor, ALL_SIDES);
        }
    }
}
